package org.jdemo.tools.bookmark;

import org.jdemo.util.CollectionUtil;
import org.jdemo.util.IOUtil;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * BookmarkFactory
 *
 * @author longlin(longlin@cyou-inc.com)
 * @date 2014-3-10
 * @since V1.0
 */
public class BookmarkFactory {
    /**
     * 章节
     */
    public static final String[] SECTION_REGEXES = {
            "^第(.+)章(.*)",
            "^附录(.*)",
    };

    /**
     * 小节，隶属于章节
     */
    public static final String[] SUB_SECTION_REGEXES = {
            "^(([0-9A-Z]+\\.)+([0-9]+))(.*)",   //例如：1.1、A.1等
            "^本章(.*)",  //例如：本章参考资料、本章小结等
    };

    public static final String PAGE_REGEX = "(\\d+)$";

    public static List<Bookmark> buildBookmarks(String content) throws Exception{
        List<Bookmark> bookmarks = new ArrayList<Bookmark>();
        List<String> lines = CollectionUtil.split(content, "\n");

        Bookmark preBookmark = null;
        for (int i = 0; i < lines.size(); i++) {
            try {
                String line = lines.get(i).trim();
                if (line.length() > 0) {
                    if (isMatched(line, SECTION_REGEXES)) {
                        Bookmark section = buildBookmark(1, line);
                        bookmarks.add(section);
                        preBookmark = section;
                    } else if (preBookmark != null && isMatched(line, SUB_SECTION_REGEXES)) {
                        Integer subSectionLevel = getSubSectionLevel(line);
                        if (subSectionLevel != null) {
                            Bookmark subSection = buildBookmark(subSectionLevel, line);
                            Integer preBookmarkLevel = preBookmark.getLevel() + 1;
                            Bookmark preBookmarkParent = preBookmark;
                            while (subSectionLevel < preBookmarkLevel) {
                                preBookmarkLevel = preBookmarkLevel - 1;
                                preBookmarkParent = preBookmarkParent.getParent();
                            }
                            preBookmarkParent.addChild(subSection);
                            subSection.setParent(preBookmarkParent);
                            preBookmark = subSection;
                        }
                    } else {
                        Bookmark noSection = buildBookmark(1, line);
                        bookmarks.add(noSection);
                        preBookmark = noSection;
                    }
                }
            } catch (Exception e) {
                throw new Exception("line " + i + " was error", e);
            }
        }
        return bookmarks;
    }

    private static Bookmark buildBookmark(int level, String line) {
        Bookmark bookmark = new Bookmark(level);
        Pattern pattern = Pattern.compile(PAGE_REGEX);
        Matcher matcher = pattern.matcher(line);
        if (matcher.find()) {
            Integer page = Integer.parseInt(matcher.group());
            String title = trim(line.replaceAll(PAGE_REGEX, "").replaceAll("\\-{5,}", ""));
            bookmark.setTitle(title);
            bookmark.setPage(page);
        } else {
            String title = trim(line.replaceAll("\\-{5,}", ""));
            bookmark.setTitle(title);
        }
        return bookmark;
    }

    private static boolean isMatched(String s, String[] regexes) {
        for (String regex : regexes) {
            if (s.matches(regex)) {
                return true;
            }
        }
        return false;
    }

    private static Integer getSubSectionLevel(String line) {
        for (int i = 0; i < SUB_SECTION_REGEXES.length; i++) {
            String subSectionRegex = SUB_SECTION_REGEXES[i];
            Pattern pattern = Pattern.compile(subSectionRegex);
            Matcher matcher = pattern.matcher(line);
            if (matcher.matches()) {
                if (i == 0) {
                    return matcher.group(1).split("\\.").length;
                }
            }
            i++;
        }
        return null;
    }

    private static String trim(String s) {
        return s.replaceAll("^(\\u3000|\\s)+", "").replaceAll("(\\u3000|\\s)+$", "").trim();
    }

    public static void main(String[] args) throws Exception{
        String content = IOUtil.readFile(new File("F:\\temp\\bookmark\\推荐系统实践.txt"), "gbk");
        List<Bookmark> bookmarks = buildBookmarks(content);
        System.out.println(bookmarks.size());
        for (Bookmark bookmark : bookmarks) {
            System.out.println(bookmark.toXML(0));
        }
    }
}
